package com.iwhalecloud.bss.kite.cucc.order.accept.chain.impl;

import com.iwhalecloud.bss.kite.client.vo.common.PromotionItemVO;
import com.iwhalecloud.bss.kite.client.vo.spec.PromoterVO;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts2;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.iwhalecloud.bss.kite.cucc.order.accept.chain.AbstractOrderHandler;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItem;
import com.iwhalecloud.bss.kite.dataservice.entity.PmPromotion;
import com.iwhalecloud.bss.kite.dataservice.entity.order.DevStaffInfo;
import com.iwhalecloud.bss.kite.dataservice.entity.order.OrderItemChange;
import com.iwhalecloud.bss.kite.dataservice.mapper.order.PmPromotionMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.other.SalesPartyMapper;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.order.client.dto.OrderContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataProdInst;
import com.ztesoft.bss.order.base.consts.IKeyValues;
import com.ztesoft.bss.order.base.consts.KeyValues;
import com.ztesoft.bss.order.base.posservice.PosPromotion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 促销项处理
 */
@Component
public class DevStaffInfoHandler extends AbstractOrderHandler {
    @Autowired
    private SalesPartyMapper salesPartyMapper;

    @Autowired
    private PmPromotionMapper pmPromotionMapper;

    @Resource
    private IQuerySceneInstService querySceneInstService;

    @Override
    public void doHandle(OrderRequest request) {
        List<String> sceneInstIds = request.getSceneInstIds();
        // 接口促销人处理
        if (KeyConsts.ACCEP_MODE_O.equals(request.getAcceptMode())) {
            for (String sceneInstId : sceneInstIds) {
                setInterPromotion(request, sceneInstId);
            }
        }
        // 前台促销人处理
        else {
            setPromotion(request);
        }
    }

    /**
     * // 前台受理处理 // 1.接入产品实例促销项处理：1.1 实例动作为A ， 不需要加服务提供过滤。1.2 带服务提供查询，不考虑实例动作。
     * // 2.功能产品实例促销项处理：2.1 实例动作为A ， 不需要加服务提供过滤。
     * // 3.终端产品实例促销项处理：3.1 实例动作为A 且服务提供为-1，增加条件过滤查询 ： promotion_code='A104'
     * // 4.销售品实例促销项处理：4.1 实例动作为A ， 不需要加服务提供过滤。
     * // 5.可选包实例促销项处理：5.1 实例动作为A ， 不需要加服务提供过滤。
     * // 6.新增“优惠续约”场景的优惠可选包促销项
     *
     * @param request
     */
    private void setPromotion(OrderRequest request) {
        List<OrderItem> orderItems = OrderContainer.ofRequest(request).listOrderItems();
        List<PromotionItemVO> promotionItems = new ArrayList<>();
        request.getSceneInstIds().forEach(t -> {
            List<PromotionItemVO> promotionItemList = querySceneInstService.getExtParameterValue(t, KeyConsts.PROMOTION_ITEM);
            if (!KiteListUtils.isEmpty(promotionItemList)) {
                promotionItems.addAll(promotionItemList);
            }
        });

        if (KiteListUtils.isEmpty(promotionItems)) {
            return;
        }

        request.getGroupInstContainer().setPromotionItemMap(KiteListUtils.groupBy(promotionItems, "promotionId"));

        orderItems.forEach(t -> {
            // 产品层相关处理
            setProdPromotions(request, t);
            // 销售品层相关处理
            setOfferPromotions(request, t);
        });
        //产品实例带服务提供查询，不考虑实例动作
        setProductPromotions(request);
        // 特殊配置
        setSpecialPromotions(request);
    }

    /**
     * 产品实例下新增的相关实例促销项处理
     * @param request
     * @param orderItem
     */
    private void setProdPromotions(OrderRequest request, OrderItem orderItem) {
        if (!KeyConsts.OFFER_TYPE_10.equals(orderItem.getOfferKind())) {
            return;
        }
            Map<String, List<OrderItemChange>> orderItemChangeMap = request.getOrderContainer().getOrderItemChangeMap();
        String offerId = orderItem.getApplyObjSpec();
        // 筛选A变动的产品实例
        List<OrderItemChange> prodItemChanges = orderItemChangeMap.get(orderItem.getOrderItemId()).stream()
            .filter(i -> ActionType.A.name().equals(i.getActionType()) && TableConsts.ProdInst.getTableName().equals(i.getTableName()))
            .collect(Collectors.toList());
        savePromotionItems(request, prodItemChanges, null, offerId, KeyConsts.PROMOTION_TYPE_PROD, null);
        // 筛选A变动的功能产品实例
        List<OrderItemChange> prodFuncItemChanges = orderItemChangeMap.get(orderItem.getOrderItemId()).stream()
            .filter(i -> ActionType.A.name().equals(i.getActionType()) && TableConsts.ProdInstFunc.getTableName().equals(i.getTableName()))
            .collect(Collectors.toList());
        savePromotionItems(request, prodFuncItemChanges, null, offerId, KeyConsts.PROMOTION_TYPE_FUNC, null);
        // 筛选A变动的终端实例
        List<OrderItemChange> mktItemChanges = orderItemChangeMap.get(orderItem.getOrderItemId()).stream()
            .filter(i -> ActionType.A.name().equals(i.getActionType()) && TableConsts.OfferResInstRelExt.getTableName().equals(i.getTableName()))
            .collect(Collectors.toList());
        savePromotionItems(request, mktItemChanges, "-1", offerId, KeyConsts.PROMOTION_TYPE_MKT, "A104");
    }

    /**
     * 销售品，可选包的促销项处理
     * @param request
     * @param orderItem
     */
    private void setOfferPromotions(OrderRequest request, OrderItem orderItem) {
        Map<String, List<OrderItemChange>> orderItemChangeMap = request.getOrderContainer().getOrderItemChangeMap();
        // 筛选A变动的销售品（包括可选包，销售品）
        List<OrderItemChange> offerItemChanges = orderItemChangeMap.get(orderItem.getOrderItemId()).stream()
            .filter(i -> ActionType.A.name().equals(i.getActionType()) && TableConsts.OfferInst.getTableName().equals(i.getTableName()))
            .collect(Collectors.toList());
        savePromotionItems(request, offerItemChanges, null, orderItem.getApplyObjSpec(), KeyConsts.PROMOTION_TYPE_OFFER, null);
    }

    /**
     * 产品实例带服务提供查询，不考虑实例动作
     * @param request
     */
    private void setProductPromotions(OrderRequest request) {
        List<OrderItemChange> orderItemChanges = OrderContainer.ofRequest(request).listOrderItemChanges();
        List<OrderItemChange> allProdItemChanges = orderItemChanges.stream()
            .filter(t -> TableConsts.ProdInst.getTableName().equals(t.getTableName())).collect(Collectors.toList());
        allProdItemChanges.forEach(t -> {
            OrderItem orderItem = OrderContainer.ofRequest(request).getOrderItem(t.getOrderItemId());
            String serviceOfferId = orderItem.getServiceOfferId();
            String baseOfferId = orderItem.getApplyObjSpec();
            List<OrderItemChange> itemchgs = new ArrayList<>();
            itemchgs.add(t);
            savePromotionItems(request, itemchgs, serviceOfferId, baseOfferId, KeyConsts.PROMOTION_TYPE_PROD, null);
        });
    }

    /**
     * 特殊配置促销项处理
     * @param request
     */
    private void setSpecialPromotions(OrderRequest request) {
        List<OrderItemChange> orderItemChanges = OrderContainer.ofRequest(request).listOrderItemChanges();
        DcPublic dcPublic = DcPublicCache.get(KeyConsts2.DC_PUBLIC_ADDOFFER_STYPE, KeyConsts.LIMIT_REGIONID_PKEY);
        if (!ObjectUtils.isEmpty(dcPublic)) {
            List<OrderItemChange> specialItemChgs = orderItemChanges.stream().filter(t -> {
                return TableConsts.OfferInst.getTableName().equals(t.getTableName())
                    && ActionType.M.name().equals(t.getActionType()) && dcPublic.getCodea().equals(t.getFieldName())
                    && dcPublic.getCodeb().equals(t.getFieldValue());
            }).collect(Collectors.toList());
            specialItemChgs.forEach(t -> {
                OrderItem orderItem = OrderContainer.ofRequest(request).getOrderItem(t.getOrderItemId());
                String baseOfferId = orderItem.getApplyObjSpec();
                List<OrderItemChange> itemchgs = new ArrayList<>();
                itemchgs.add(t);
                savePromotionItems(request, itemchgs, null, baseOfferId, KeyConsts.PROMOTION_TYPE_PROD, null);
            });
        }
    }

    /**
     * 查询并保存促销项
     *
     * @param orderItemChanges
     * @param offerId
     */
    private void savePromotionItems(OrderRequest request, List<OrderItemChange> orderItemChanges, String serviceOfferId,
        String offerId, String promotionType, String promotionCode) {
        if (KiteListUtils.isEmpty(orderItemChanges)) {
            return;
        }
        List<String> objIdList = new ArrayList<>();
        orderItemChanges.forEach(i -> {
            objIdList.add(i.getSpecId());
        });

        List<PmPromotion> pmPromotions = pmPromotionMapper.listCommonPromotionItems(request.getLanId(),
            request.getRegionId(), serviceOfferId, promotionCode, promotionType, offerId, objIdList);

        setDevStaffInfo(request, orderItemChanges.get(0).getOrderItemId(), pmPromotions);
    }

    private void setDevStaffInfo(OrderRequest request, String orderItemId, List<PmPromotion> pmPromotions) {
        if (KiteListUtils.isNotEmpty(pmPromotions)) {
            pmPromotions.forEach(pmPromotion -> {
                List<PromotionItemVO> targetPmPromotions = request.getGroupInstContainer().getPromotionItemMap()
                    .get(pmPromotion.getPromotionId());
                if (KiteListUtils.isNotEmpty(targetPmPromotions)) {
                    targetPmPromotions.forEach(t -> {
                        String salesPartyCode = t.getPromoterVO() != null ? t.getPromoterVO().getSalesPartyCode() : "";
                        DevStaffInfo devStaffInfo = new DevStaffInfo();
                        devStaffInfo.setObjId(pmPromotion.getObjectId());
                        devStaffInfo.setRelationTypeId(pmPromotion.getPromotionId());
                        setDevStaffInfoProp(request, orderItemId, getObjType(pmPromotion.getPromotionType()), devStaffInfo);
                        setStaffInfoProp(request.getLanId(), salesPartyCode, devStaffInfo);
                        Map<String, List<DevStaffInfo>> devStaffInfoMap = request.getOrderContainer().getDevStaffInfoMap();
                        devStaffInfoMap.computeIfAbsent(orderItemId, value -> new ArrayList<>()).add(devStaffInfo);
                    });
                }
            });
        }
    }

    /**
     * 接口受理促销项处理
     *
     * @param request
     * @param sceneInstId
     */
    @SuppressWarnings("unchecked")
    private void setInterPromotion(OrderRequest request, String sceneInstId) {
        Map<String, Object> extParameterMap = request.getGroupInstContainer().getKeyValueMap().get(sceneInstId);
        if (KiteMapUtils.isEmpty(extParameterMap)) {
            return;
        }
        List<OrderItemChange> orderItemChanges = OrderContainer.ofRequest(request).listOrderItemChanges();

        for (Map.Entry<String, Object> entity : extParameterMap.entrySet()) {
            OrderItemChange itemChange = orderItemChanges.stream()
                .filter(t -> (KeyConsts.PosPromotion + t.getInstId()).equals(entity.getKey())).findAny().orElse(null);
            if (ObjectUtils.isEmpty(itemChange)) {
                continue;
            }
            setInterdevStaffInfoMap((List<PosPromotion>) entity.getValue(), itemChange, request);
        }
    }

    private void setInterdevStaffInfoMap(List<PosPromotion> posPromotionList, OrderItemChange orderItemChange,
        OrderRequest request) {
        List<DevStaffInfo> devStaffInfos = new ArrayList<>();
        for (PosPromotion posPromotion : posPromotionList) {
            DevStaffInfo devStaffInfo = new DevStaffInfo();
            devStaffInfo.setObjId(orderItemChange.getSpecId());
            setRelationTypeId(posPromotion, orderItemChange, devStaffInfo);
            setStaffInfoProp(posPromotion.getLan_id(), posPromotion.getSale_code(), devStaffInfo);
            setDevStaffInfoProp(request, orderItemChange.getOrderItemId(), getObjType(orderItemChange.getTableName()), devStaffInfo);
            Map<String, List<DevStaffInfo>> devStaffInfoMap = request.getOrderContainer().getDevStaffInfoMap();
            if (devStaffInfoMap.containsKey(orderItemChange.getOrderItemId())) {
                devStaffInfoMap.get(orderItemChange.getOrderItemId()).add(devStaffInfo);
            }
            else {
                devStaffInfos.add(devStaffInfo);
                devStaffInfoMap.put(orderItemChange.getOrderItemId(), devStaffInfos);
            }
        }
    }

    private void setStaffInfoProp(String lanId, String salesPartyCode, DevStaffInfo devStaffInfo) {
        List<PromoterVO> promoterList = salesPartyMapper.getPromoter(salesPartyCode, lanId);
        if (!KiteListUtils.isEmpty(promoterList)) {
            PromoterVO promoter = promoterList.get(0);
            devStaffInfo.setDevStaffId(promoter.getPartyId());
            devStaffInfo.setDevOrgId(promoter.getOrgId());
            devStaffInfo.setPartyName(promoter.getSalesPartyName());
        }
    }

    private void setRelationTypeId(PosPromotion posPromotion, OrderItemChange orderItemChange,
        DevStaffInfo devStaffInfo) {
        if (KiteStringUtils.isEmpty(posPromotion.getPromotionId())) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("lanId", posPromotion.getLan_id());
            map.put("objectId", orderItemChange.getSpecId());
            map.put("promotionType", getPromotionType(orderItemChange.getTableName()));
            String promotionId = salesPartyMapper.getPromotionId(map);
            devStaffInfo.setRelationTypeId(promotionId);
        }
        else {
            devStaffInfo.setRelationTypeId(posPromotion.getPromotionId());
        }
    }

    private void setDevStaffInfoProp(OrderRequest request, String orderItemId, String objType, DevStaffInfo devStaffInfo) {
        devStaffInfo.setDevStaffInfoId(SeqUtils.getNext(TableConsts.DevStaffInfo));
        devStaffInfo.setLanId(request.getLanId());
        devStaffInfo.setCustOrderId(request.getCustOrderId());
        devStaffInfo.setCustId(request.getCustId());
        devStaffInfo.setOrderItemId(orderItemId);
        devStaffInfo.setStatusCd(IKeyValues.STATUS_CD_1000);
        devStaffInfo.setOrderType(KeyValues.ORDER_TYPE_ORDERITEM);
        devStaffInfo.setDevStaffType(CoreDataProdInst.PRI_C_0016_1000);
        devStaffInfo.setChangeTimes("0");
        devStaffInfo.setCreateDate(request.getAcceptDate());
        devStaffInfo.setUpdateDate(request.getAcceptDate());
        devStaffInfo.setStatusDate(request.getAcceptDate());
        devStaffInfo.setFinishTime(request.getAcceptDate());
        devStaffInfo.setCreateStaff(request.getStaffId());
        devStaffInfo.setObjType(objType);
    }

    private String getPromotionType(String tableName) {
        if (TableConsts.ProdInst.getTableName().equals(tableName)) {
            return KeyConsts.PROMOTION_TYPE_PROD;
        }
        if (TableConsts.ProdInstFunc.getTableName().equals(tableName)) {
            return KeyConsts.PROMOTION_TYPE_FUNC;
        }
        if (TableConsts.OfferInst.getTableName().equals(tableName)) {
            return KeyConsts.PROMOTION_TYPE_OFFER;
        }
        if (TableConsts.OfferResInstRelExt.getTableName().equals(tableName)) {
            return KeyConsts.PROMOTION_TYPE_MKT;
        }
        return "";
    }

    private String getObjType(String tableName) {
        if (TableConsts.ProdInst.getTableName().equals(tableName)) {
            return CoreDataProdInst.PRI_C_0015_120000;
        }
        if (TableConsts.ProdInstFunc.getTableName().equals(tableName)) {
            return CoreDataProdInst.PRI_C_0015_120000;
        }
        if (TableConsts.OfferInst.getTableName().equals(tableName)) {
            return CoreDataProdInst.PRI_C_0015_120100;
        }
        if (TableConsts.OfferResInstRelExt.getTableName().equals(tableName)) {
            return CoreDataProdInst.PRI_C_0015_180100;
        }
        return "";
    }
}
